<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <link rel="icon" href="data:;base64,iVBORw0KGgo=">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>存储监控数据展示</title>
  <style>
    /* 保持原有样式不变 */
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
    }

    .top-right-actions {
      position: absolute;
      top: 20px;
      right: 20px;
    }
    .container {
      position: relative;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
    }

    h1 {
      color: #333;
    }

    .filter {
      display: flex;
      align-items: center;
      gap: 10px;
      margin: 20px 0;
      padding: 10px;
      background: #f5f5f5;
      border-radius: 4px;
    }

    .filter select,
    .filter button {
      padding: 8px 12px;
      border: 1px solid #ddd;
      border-radius: 4px;
    }

    .filter .collect-btn {
      margin-left: auto;
    }

    table {
      width: 100%;
      border-collapse: collapse;
      margin-top: 20px;
    }

    th,
    td {
      padding: 12px;
      text-align: left;
      border-bottom: 1px solid #ddd;
    }

    th {
      background-color: #f9f9f9;
      font-weight: bold;
      cursor: pointer;
      user-select: none;
    }

    th:hover {
      background-color: #f0f0f0;
    }

    th .sort-icon {
      margin-left: 5px;
      font-size: 0.8em;
      opacity: 0.6;
    }

    .loading {
      color: #666;
      padding: 20px;
    }

    .error {
      color: #dc3545;
      padding: 20px;
    }

    .high-usage {
      color: #dc3545;
      font-weight: bold;
    }

    .medium-usage {
      color: #ffc107;
      font-weight: bold;
    }

    tr:hover {
      background-color: #f9f9f9;
    }

    #status {
      margin-top: 10px;
      padding: 12px;
      border-radius: 4px;
      text-align: center;
      font-weight: bold;
      transition: all 0.3s ease;
    }

    #status.collecting {
      background-color: #ffc107;
      color: #333;
    }

    #status.success {
      background-color: #28a745;
      color: #fff;
    }

    #status.failed {
      background-color: #dc3545;
      color: #fff;
    }

    .cache-indicator {
      color: #666;
      font-size: 0.9em;
      margin-left: 10px;
      padding: 2px 5px;
      background: #f0f0f0;
      border-radius: 3px;
    }
  </style>
</head>

<body>
  <div id="mainContent" style="display:none;">

  <div class="container">
    <h1>天宫环境存储使用情况</h1>
    <div class="top-right-actions">
        <button id="logoutBtn" class="collect-btn">退出登录</button>
    </div>

    <div class="filter">
      <label for="namespace">选择命名空间：</label>
      <select id="namespace">
        <option value="">全部命名空间</option>
      </select>

      <button id="queryBtn">查询数据</button>
      <input type="text" id="searchInput" placeholder="模糊搜索...">
      <button id="searchBtn">搜索</button>
      <span id="lastUpdate" class="cache-indicator"></span>
      <button id="collectBtn" class="collect-btn">马上采集数据</button>
      
    </div>

    <div id="status"></div>

    <div id="loading" class="loading">加载中...</div>
    <div id="error" class="error" style="display: none;"></div>
    <table id="dataTable" style="display: none;">
      <thead>
        <tr>
          <th data-sort="namespace">命名空间<span class="sort-icon"></span></th>
          <th data-sort="app">应用<span class="sort-icon"></span></th>
          <th data-sort="pvcName">PVC<span class="sort-icon"></span></th>
          <th data-sort="totalSize">总大小<span class="sort-icon"></span></th>
          <th data-sort="usedSize">已使用<span class="sort-icon"></span></th>
          <th data-sort="availableSize">可用<span class="sort-icon"></span></th>
          <th data-sort="usagePercent">使用率<span class="sort-icon"></span></th>
          <th data-sort="createdAt">采集时间<span class="sort-icon"></span></th>
        </tr>
      </thead>
      <tbody id="tableBody"></tbody>
    </table>
  </div>

  <script>
    const API_BASE_URL = '/api/storage';
    const collectBtn = document.getElementById('collectBtn');
    const statusDiv = document.getElementById('status');
    let cachedData = [];
    let currentSort = { key: 'createdAt', order: 'desc' };

    function initSortEvents() {
      document.querySelectorAll('th[data-sort]').forEach(th => {
        th.addEventListener('click', () => {
          const sortKey = th.getAttribute('data-sort');
          if (currentSort.key === sortKey) {
            currentSort.order = currentSort.order === 'asc' ? 'desc' : 'asc';
          } else {
            currentSort.key = sortKey;
            currentSort.order = 'asc';
          }
          renderTableWithCache();
          updateSortIcons();
        });
      });
    }

    function updateSortIcons() {
      document.querySelectorAll('th[data-sort] .sort-icon').forEach(icon => {
        icon.textContent = '';
      });
      const currentIcon = document.querySelector(`th[data-sort="${currentSort.key}"] .sort-icon`);
      currentIcon.textContent = currentSort.order === 'asc' ? '↑' : '↓';
    }

    async function fetchNamespaces() {
      try {
        const token = localStorage.getItem('token');
        const response = await fetch(`${API_BASE_URL}/namespaces`, {
          headers: { 'Authorization': `Bearer ${token}` }
        });
        if (!response.ok) throw new Error(`状态码：${response.status}`);
        const namespaces = await response.json();
        const select = document.getElementById('namespace');
        select.innerHTML = '<option value="">全部命名空间</option>';
        namespaces.forEach(ns => {
          const option = document.createElement('option');
          option.value = ns;
          option.textContent = ns;
          select.appendChild(option);
        });
      } catch (err) {
        console.error('命名空间加载失败：', err);
        showError(`命名空间加载失败：${err.message}（将使用缓存数据）`);
      }
    }

    function renderTableWithCache() {
      const namespace = document.getElementById('namespace').value;
      const table = document.getElementById('dataTable');
      const tableBody = document.getElementById('tableBody'); // 先声明变量
      tableBody.innerHTML = ''; // 再使用变量

      let filteredData = cachedData;
      if (namespace) {
        filteredData = cachedData.filter(item => item.namespace === namespace);
      }

      const sortedData = sortData([...filteredData], currentSort.key, currentSort.order);

      if (sortedData.length === 0) {
        tableBody.innerHTML = '<tr><td colspan="8" style="text-align: center;">暂无数据，请点击"马上采集数据"获取最新信息</td></tr>';
      } else {
        sortedData.forEach(data => {
          const row = document.createElement('tr');
          const usagePercent = parseFloat(data.usagePercent);
          const usageClass = usagePercent >= 90 ? 'high-usage' : 
                             usagePercent >= 70 ? 'medium-usage' : '';
          
          row.innerHTML = `
            <td>${data.namespace}</td>
            <td>${data.app}</td>
            <td>${data.pvcName || '-'}</td>
            <td>${data.totalSize}</td>
            <td>${data.usedSize}</td>
            <td>${data.availableSize}</td>
            <td class="${usageClass}">${data.usagePercent}</td>
            <td>${data.created_at}</td>
          `;
          tableBody.appendChild(row);
        });
      }

      table.style.display = 'table';
      updateSortIcons();
    }

    function sortData(data, key, order) {
      return data.sort((a, b) => {
        let valueA, valueB;
        
        if (key === 'usagePercent') {
          valueA = parseFloat(a[key].replace(/[^\d.]/g, '')) || 0;
          valueB = parseFloat(b[key].replace(/[^\d.]/g, '')) || 0;
        } else if (key === 'createdAt') {
          valueA = new Date(a.created_at).getTime() || 0;
          valueB = new Date(b.created_at).getTime() || 0;
        } else if (['totalSize', 'usedSize', 'availableSize'].includes(key)) {
          valueA = parseSizeToBytes(a[key]);
          valueB = parseSizeToBytes(b[key]);
        } else {
          valueA = a[key]?.toString().toLowerCase() || '';
          valueB = b[key]?.toString().toLowerCase() || '';
        }

        if (valueA < valueB) return order === 'asc' ? -1 : 1;
        if (valueA > valueB) return order === 'asc' ? 1 : -1;
        return 0;
      });
    }

    function parseSizeToBytes(sizeStr) {
      if (!sizeStr) return 0;
      const units = { 
        'B': 1, 
        'K': 1024, 'KB': 1024,  // K和KB都对应1024
        'M': 1024**2, 'MB': 1024**2,  // M和MB都对应1024²
        'G': 1024**3, 'GB': 1024**3,  // G和GB都对应1024³
        'T': 1024**4, 'TB': 1024**4   // T和TB都对应1024⁴
      };
      const match = sizeStr.match(/^(\d+(\.\d+)?)\s*([KMGT]?B?)$/i);
      if (!match) return 0;
      const value = parseFloat(match[1]);
      const unit = match[3].toUpperCase(); // 转为大写统一处理
      return value * (units[unit] || 0);
    }

    collectBtn.addEventListener('click', async () => {
      collectBtn.disabled = true;
      statusDiv.style.display = 'block'; 
      statusDiv.textContent = '正在采集数据，请稍候...';
      statusDiv.className = 'collecting';

      try {
        const response = await fetch(`${API_BASE_URL}/collect`, {
          method: 'POST',
          headers: { 
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${localStorage.getItem('token')}`
          }
        });
        if (!response.ok) throw new Error(`HTTP 错误！状态码：${response.status}`);
        const result = await response.json();

        if (result.success) {
          statusDiv.textContent = '数据采集成功！正在刷新数据...';
          statusDiv.className = 'success';
          await fetchData(); // 立即刷新数据
        } else {
          statusDiv.textContent = `采集失败：${result.message}`;
          statusDiv.className = 'failed';
        }
      } catch (error) {
        statusDiv.textContent = `采集失败：${error.message}（请检查服务是否可用）`;
        statusDiv.className = 'failed';
      } finally {
        setTimeout(() => {
          statusDiv.textContent = '';
          statusDiv.className = '';
          collectBtn.disabled = false;
        }, 2000);
      }
    });

    function showError(message) {
      const errorDiv = document.getElementById('error');
      errorDiv.textContent = message;
      errorDiv.style.display = 'block';
      if (cachedData.length > 0) {
        document.getElementById('dataTable').style.display = 'table';
      }
    }

  function checkTokenExpiration() {
    const token = localStorage.getItem('token');
    const expiration = localStorage.getItem('tokenExpiration');
    
    if (token && expiration && new Date().getTime() > parseInt(expiration)) {
      localStorage.removeItem('token');
      localStorage.removeItem('tokenExpiration');
      window.location.href = 'login.html'; // 修复：直接跳转登录页
    }
  }

  function setupTokenCheck() {
    setInterval(checkTokenExpiration, 60000);
  }

  document.getElementById('logoutBtn').addEventListener('click', function() {
    localStorage.removeItem('token');
    localStorage.removeItem('tokenExpiration');
    
    const statusDiv = document.getElementById('status');
    statusDiv.textContent = '退出成功，正在跳转...';
    statusDiv.className = 'success';
    statusDiv.style.display = 'block';
    
    setTimeout(() => {
      window.location.href = 'login.html'; // 修复：直接跳转登录页
    }, 1000);
  });

  document.getElementById('queryBtn').addEventListener('click', fetchData);
  document.getElementById('namespace').addEventListener('change', fetchData); // 新增：选择命名空间后自动查询

  window.onload = () => {
    const token = localStorage.getItem('token');
    const expiration = localStorage.getItem('tokenExpiration');

    if (!token || !expiration || new Date().getTime() > parseInt(expiration)) {
      window.location.href = 'login.html';
      return;
    }
    document.getElementById('mainContent').style.display = 'block';

    checkTokenExpiration();
    fetchNamespaces();
    initSortEvents();
    fetchData();
    setInterval(fetchData, 30000);
    setupTokenCheck();
  };

  const searchInput = document.getElementById('searchInput');
  const searchBtn = document.getElementById('searchBtn');

  function fuzzySearch() {
    const searchText = searchInput.value.toLowerCase();
    if (!searchText) {
      renderTableWithCache();
      return;
    }
    const filteredData = cachedData.filter(item => {
      return item.namespace.toLowerCase().includes(searchText) ||
             item.app.toLowerCase().includes(searchText) ||
             item.created_at.toLowerCase().includes(searchText);
    });
    renderFilteredTable(filteredData);
  }

  function renderFilteredTable(data) {
    // 修复：先声明变量再使用
    const table = document.getElementById('dataTable');
    const tableBody = document.getElementById('tableBody');
    tableBody.innerHTML = '';

    // 修复：对搜索结果应用排序
    const sortedData = sortData([...data], currentSort.key, currentSort.order);

    if (sortedData.length === 0) {
      tableBody.innerHTML = '<tr><td colspan="7" style="text-align: center;">未找到匹配数据</td></tr>';
    } else {
      sortedData.forEach(item => {
        const row = document.createElement('tr');
        const usagePercent = parseFloat(item.usagePercent);
        const usageClass = usagePercent >= 90 ? 'high-usage' : 
                           usagePercent >= 70 ? 'medium-usage' : '';
        
        row.innerHTML = `
          <td>${item.namespace}</td>
          <td>${item.app}</td>
          <td>${item.pvcName || '-'}</td>
          <td>${item.totalSize}</td>
          <td>${item.usedSize}</td>
          <td>${item.availableSize}</td>
          <td class="${usageClass}">${item.usagePercent}</td>
          <td>${item.created_at}</td>
        `;
        tableBody.appendChild(row);
      });
    }
    table.style.display = 'table';
    updateSortIcons();
  }

  searchBtn.addEventListener('click', fuzzySearch);
  searchInput.addEventListener('keyup', function(event) {
    if (event.key === 'Enter') {
      fuzzySearch();
    }
  });

  async function fetchData() {
    const token = localStorage.getItem('token');
    checkTokenExpiration();
    
    const namespace = document.getElementById('namespace').value;
    const loading = document.getElementById('loading');
    const error = document.getElementById('error');

    loading.style.display = 'block';
    loading.textContent = "正在获取最新数据..."; // 优化提示
    error.style.display = 'none';

    try {
      let url = `${API_BASE_URL}/data`;
      if (namespace) url += `?namespace=${encodeURIComponent(namespace)}`;
      const response = await fetch(url, {
        headers: { 'Authorization': `Bearer ${token}` }
      });

      if (!response.ok) {
        if (response.status === 401) {
          localStorage.removeItem('token');
          localStorage.removeItem('tokenExpiration');
          window.location.href = 'login.html';
          return;
        }
        throw new Error(`请求失败，状态码：${response.status}`);
      }

      let dataList = await response.json();

      const pvcMap = new Map();
      dataList.forEach(item => {
        const existing = pvcMap.get(item.pvcName);
        // 转换为时间戳比较，确保获取最新记录
        const currentTime = new Date(item.created_at).getTime()

        // 如果不存在该PVC，或存在但当前记录更新，则替换
        if (!existing || currentTime > new Date(existing.created_at).getTime()) {
          pvcMap.set(item.pvcName, item);
        }
      });
      // 将Map转换为数组，得到去重后的最新数据
      cachedData = Array.from(pvcMap.values());

      document.getElementById('lastUpdate').textContent = `最后更新：${new Date().toLocaleString()}`;
      renderTableWithCache();
    } catch (err) {
      console.error('获取数据失败：', err);
      error.textContent = `获取数据失败：${err.message}`;
      error.style.display = 'block';
    } finally {
      loading.style.display = 'none';
    }
  }
  </script>
</body>

</html>
